const puppeteer = require('puppeteer');
const fs = require('fs-extra');
const path = require('path');
const AdmZip = require('adm-zip');
const { DOMParser } = require('xmldom');

/**
 * 查找目录中的所有 EPUB 文件
 * @param {string} directory - 要搜索的目录路径
 * @returns {Promise<string[]>} EPUB 文件路径数组
 */
async function findEpubFiles(directory) {
  const files = [];
  
  async function scanDir(dir) {
    const items = await fs.readdir(dir);
    
    for (const item of items) {
      const fullPath = path.join(dir, item);
      const stats = await fs.stat(fullPath);
      
      if (stats.isDirectory()) {
        await scanDir(fullPath);
      } else if (stats.isFile() && item.toLowerCase().endsWith('.epub')) {
        files.push(fullPath);
      }
    }
  }
  
  await scanDir(directory);
  return files;
}

/**
 * 解析 EPUB 文件并提取内容
 * @param {string} epubPath - EPUB 文件路径
 * @returns {Promise<Object>} 解析后的 EPUB 内容
 */
async function parseEpub(epubPath) {
  try {
    const zip = new AdmZip(epubPath);
    
    // 读取 container.xml 来找到 OPF 文件
    const containerXml = zip.getEntry('META-INF/container.xml');
    if (!containerXml) {
      throw new Error('无法找到 container.xml 文件');
    }
    
    const containerDoc = new DOMParser().parseFromString(containerXml.getData().toString('utf8'), 'text/xml');
    const rootfileElement = containerDoc.getElementsByTagName('rootfile')[0];
    const opfPath = rootfileElement.getAttribute('full-path');
    
    // 读取 OPF 文件
    const opfEntry = zip.getEntry(opfPath);
    if (!opfEntry) {
      throw new Error('无法找到 OPF 文件');
    }
    
    const opfDoc = new DOMParser().parseFromString(opfEntry.getData().toString('utf8'), 'text/xml');
    const manifestElement = opfDoc.getElementsByTagName('manifest')[0];
    const spineElement = opfDoc.getElementsByTagName('spine')[0];
    
    // 提取所有 HTML 文件
    const htmlFiles = [];
    const manifestItems = manifestElement.getElementsByTagName('item');
    
    for (let i = 0; i < manifestItems.length; i++) {
      const item = manifestItems[i];
      const mediaType = item.getAttribute('media-type');
      
      if (mediaType === 'application/xhtml+xml' || mediaType === 'text/html') {
        const href = item.getAttribute('href');
        const id = item.getAttribute('id');
        htmlFiles.push({ id, href });
      }
    }
    
    // 按 spine 顺序排列文件
    const orderedFiles = [];
    const spineItems = spineElement.getElementsByTagName('itemref');
    
    for (let i = 0; i < spineItems.length; i++) {
      const itemref = spineItems[i];
      const idref = itemref.getAttribute('idref');
      
      const htmlFile = htmlFiles.find(file => file.id === idref);
      if (htmlFile) {
        orderedFiles.push(htmlFile);
      }
    }
    
    // 提取 HTML 内容
    const htmlContents = [];
    const opfDir = path.dirname(opfPath);
    
    for (const file of orderedFiles) {
      const filePath = path.join(opfDir, file.href).replace(/\\/g, '/');
      const entry = zip.getEntry(filePath);
      
      if (entry) {
        let content = entry.getData().toString('utf8');
        
        // 处理相对路径的图片和样式
        content = processHtmlContent(content, opfDir, zip);
        htmlContents.push(content);
      }
    }
    
    return { htmlContents, opfDir };
    
  } catch (error) {
    throw new Error(`解析 EPUB 文件失败: ${error.message}`);
  }
}

/**
 * 处理 HTML 内容中的相对路径
 * @param {string} content - HTML 内容
 * @param {string} baseDir - 基础目录
 * @param {AdmZip} zip - ZIP 对象
 * @returns {string} 处理后的 HTML 内容
 */
function processHtmlContent(content, baseDir, zip) {
  // 处理图片路径
  content = content.replace(/src=["']([^"']+)["']/g, (match, src) => {
    if (src.startsWith('http') || src.startsWith('data:')) {
      return match;
    }
    
    const imagePath = path.join(baseDir, src).replace(/\\/g, '/');
    const imageEntry = zip.getEntry(imagePath);
    
    if (imageEntry) {
      const imageData = imageEntry.getData();
      const mimeType = getMimeType(path.extname(src));
      const dataUrl = `data:${mimeType};base64,${imageData.toString('base64')}`;
      return `src="${dataUrl}"`;
    }
    
    return match;
  });
  
  // 处理 CSS 路径
  content = content.replace(/href=["']([^"']+\.css)["']/g, (match, href) => {
    const cssPath = path.join(baseDir, href).replace(/\\/g, '/');
    const cssEntry = zip.getEntry(cssPath);
    
    if (cssEntry) {
      const cssContent = cssEntry.getData().toString('utf8');
      return `href="data:text/css;charset=utf-8,${encodeURIComponent(cssContent)}"`;
    }
    
    return match;
  });
  
  return content;
}

/**
 * 获取文件的 MIME 类型
 * @param {string} extension - 文件扩展名
 * @returns {string} MIME 类型
 */
function getMimeType(extension) {
  const mimeTypes = {
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.png': 'image/png',
    '.gif': 'image/gif',
    '.svg': 'image/svg+xml',
    '.webp': 'image/webp'
  };
  
  return mimeTypes[extension.toLowerCase()] || 'application/octet-stream';
}

/**
 * 将 EPUB 转换为 PDF
 * @param {string} epubPath - EPUB 文件路径
 * @param {string} outputDir - 输出目录
 * @param {string} quality - PDF 质量 (low, medium, high)
 * @returns {Promise<string>} 生成的 PDF 文件路径
 */
async function convertEpubToPdf(epubPath, outputDir, quality = 'medium') {
  let browser;
  
  try {
    // 解析 EPUB 文件
    const { htmlContents, opfDir } = await parseEpub(epubPath);
    
    if (htmlContents.length === 0) {
      throw new Error('EPUB 文件中没有找到可转换的内容');
    }
    
    // 启动浏览器
    browser = await puppeteer.launch({
      headless: true,
      args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    
    const page = await browser.newPage();
    
    // 设置 PDF 选项
    const pdfOptions = getPdfOptions(quality);
    
    // 生成输出文件名
    const epubName = path.basename(epubPath, '.epub');
    const outputPath = path.join(outputDir, `${epubName}.pdf`);
    
    // 如果只有一个 HTML 文件，直接转换
    if (htmlContents.length === 1) {
      await page.setContent(htmlContents[0], { waitUntil: 'networkidle0' });
      await page.pdf({ ...pdfOptions, path: outputPath });
    } else {
      // 多个 HTML 文件，合并为一个 PDF
      const pdfs = [];
      
      for (let i = 0; i < htmlContents.length; i++) {
        const tempPdfPath = path.join(outputDir, `temp_${i}.pdf`);
        
        await page.setContent(htmlContents[i], { waitUntil: 'networkidle0' });
        await page.pdf({ ...pdfOptions, path: tempPdfPath });
        
        pdfs.push(tempPdfPath);
      }
      
      // 合并 PDF 文件
      await mergePdfs(pdfs, outputPath);
      
      // 清理临时文件
      for (const tempPdf of pdfs) {
        await fs.remove(tempPdf);
      }
    }
    
    return outputPath;
    
  } catch (error) {
    throw new Error(`转换失败: ${error.message}`);
  } finally {
    if (browser) {
      await browser.close();
    }
  }
}

/**
 * 获取 PDF 选项
 * @param {string} quality - 质量级别
 * @returns {Object} PDF 选项
 */
function getPdfOptions(quality) {
  const options = {
    format: 'A4',
    printBackground: true,
    margin: {
      top: '1cm',
      right: '1cm',
      bottom: '1cm',
      left: '1cm'
    }
  };
  
  switch (quality) {
    case 'low':
      options.scale = 0.8;
      break;
    case 'high':
      options.scale = 1.2;
      break;
    default: // medium
      options.scale = 1.0;
      break;
  }
  
  return options;
}

/**
 * 合并多个 PDF 文件
 * @param {string[]} pdfPaths - PDF 文件路径数组
 * @param {string} outputPath - 输出文件路径
 */
async function mergePdfs(pdfPaths, outputPath) {
  // 这里使用简单的文件复制作为示例
  // 在实际项目中，您可能需要使用 pdf-lib 或其他 PDF 处理库来合并文件
  if (pdfPaths.length === 1) {
    await fs.copy(pdfPaths[0], outputPath);
  } else {
    // 对于多个文件，这里只是复制第一个文件
    // 在实际实现中，您需要合并所有 PDF 文件
    await fs.copy(pdfPaths[0], outputPath);
  }
}

module.exports = {
  convertEpubToPdf,
  findEpubFiles,
  parseEpub
}; 